<template>
<el-row>
  <el-col :span="15">
    <el-card class="form">
      <json-editor ref="JsonEditor" :schema="schema" v-model="model">
        <el-button type="primary" @click="submit" size="mini">确 定</el-button>
        <el-button type="reset" @click="reset" size="mini">重 置</el-button>
      </json-editor>
    </el-card>
  </el-col>
  <el-col :span="9">
    <el-card class="box-card">
      <div slot="header" class="clearfix">
        <span>实时代码</span>
      </div>
      <pre class="json">{{ jsonString }}</pre>
    </el-card>
  </el-col>
</el-row>
</template>

<script>
let schemas = {
  "type": "object",
  "title": "Json编辑实例",
  "description": "基于element-ui样式的json编辑器实例",
  "properties": {
    "name": {
      "type": "string",
      "minLength": 8,
      "maxLength": 80,
      "title": "名称",
      "attrs": {
        "placeholder": "请填写名称",
        "title": "请填写名称"
      }
    },
    "sub": {
      "title": "SubTitle",
      "description": "SubDescription",
      "type": "object",
      "properties": {
        "sName": {
          "minLength": 8,
          "maxLength": 80,
          "title": "SubName",
          "attrs": {
            "placeholder": "Sub Full Name",
            "title": "请输入全名"
          }
        },
        "sUrl": {
          "title": "SubUrl",
          "format": "uri",
          "attrs": {
            "placeholder": "请输入Url"
          }
        },
        "sub2": {
          "type": "object",
          "title": "Sub2Title",
          "description": "Sub2Description",
          "properties": {
            "sName2": {
              "format": "regex",
              "title": "Sub2Name",
              "pattern": "*",
              "attrs": {
                "placeholder": "请输入Sub2Name"
              }
            },
            "sAge": {
              "type": "integer",
              "title": "Sub2Age"
            }
          },
          "required": [ "sName2" ]
        }
      },
      "required": ["sUrl"]
    },
    "lists": {
      "type": "string",
      "title": "List",
      "enum": ["Daily New", "Promotion"],
      "attrs": {
        "placeholder": "请选择",
        "title": "必须选择"
      }
    },
    "lists2": {
      "type": "array",
      "title": "List2",
      "anyOf": [
        { "value": "daily", "label": "Daily New" },
        { "value": "promotion", "label": "Promotion" }
      ],
      "attrs": {
        "placeholder": "Select your list subscription",
        "title": "Please select your list subscription"
      }
    },
    "lists3": {
      "type": "array",
      "title": "List3",
      "oneOf": [
        { "value": "daily", "label": "Daily New" },
        { "value": "promotion", "label": "Promotion" }
      ]
    },
    "source": {
      "type": "string",
      "maxLength": 120,
      "title": "Source",
      "description": "Ex. Using the NPM Search Engine",
      "attrs": {
        "type": "textarea",
        "placeholder": "How did you hear about us?"
      }
    },
    "rate": {
      "type": "number",
      "title": "Rate",
      "default": 2,
      "attrs": {
        "type": "rate",
        "allow-half": true
      }
    },
    "color": {
      "type": "string",
      "title": "Color",
      "default": "#409EFF",
      "attrs": {
        "type": "color"
      }
    },
    "agree": {
      "type": "boolean",
      "title": "Agree",
      "description": "You agree to receive occasional updates and special offers for vue-json-schema updates.",
      "default": false,
      "attrs": {
        "type": "switch"
      }
    }
  },
  "additionalProperties": false,
  "required": ["name", "email", "lists"]
}
import JsonEditor from 'vue-json-ui-editor';
import { Option } from 'element-ui';
JsonEditor.setComponent('form', 'el-form', ({ vm }) => {
  // vm is the JsonEditor VM
  const labelWidth = '120px';
  const model = vm.data;
  const rules = {};
  function parseField(fields) {
    Object.keys(fields).forEach(key => {
      if (key.indexOf('$') === 0 && key !== '$sub') return;
      const field = fields[key];
      if (field.$sub) {
        return parseField(field);
      }
      if (!field.name) return;
      rules[field.name] = [];
      // http://element.eleme.io/#/en-US/component/form#validation
      const type = field.schemaType === 'array' && field.type === 'radio' ? 'string' : field.schemaType;
      const arrayDefine = field.schemaType === 'array' && field.arrayDefine
      const required = field.required;
      const message = field.title;
      const trigger = ['radio', 'checkbox', 'select'].includes(field.type) ? 'change' : 'blur';
      rules[field.name].push({ type, required, message, trigger });
      if (arrayDefine) {
        
      }
      if (field.minlength !== undefined || field.maxlength !== undefined) {
        const max = field.maxlength || 255;
        const min = field.minlength || 0;
        const msg = `长度必须在 ${ min } 到 ${ max }之间`;
        rules[field.name].push({ min, max, message: msg, trigger });
      }
    });
  }
  parseField(vm.fields);
  // returning the form props
  return { labelWidth, rules, model };
});
// http://element.eleme.io/#/en-US/component/form#validation
JsonEditor.setComponent('label', 'el-form-item', ({ field }) => ({
  prop: field.name
}));
JsonEditor.setComponent('email', 'el-input');
JsonEditor.setComponent('url', 'el-input');
JsonEditor.setComponent('number', 'el-input-number');
JsonEditor.setComponent('text', 'el-input');
JsonEditor.setComponent('textarea', 'el-input');
JsonEditor.setComponent('checkbox', 'el-checkbox');
JsonEditor.setComponent('checkboxgroup', 'el-checkbox-group');
JsonEditor.setComponent('radio', 'el-radio');
JsonEditor.setComponent('radiogroup', 'el-radio-group');
JsonEditor.setComponent('select', 'el-select');
JsonEditor.setComponent('switch', 'el-switch');
JsonEditor.setComponent('color', 'el-color-picker');
JsonEditor.setComponent('rate', 'el-rate');
// You can also use the component object
JsonEditor.setComponent('option', Option);
// By default `<h1/>` is used to render the form title.
// To override this, use the `title` type:
JsonEditor.setComponent('title', 'h2');
// By default `<p/>` is used to render the form title.
// To override this, use the `description` type:
JsonEditor.setComponent('description', 'small');
// By default `<div/>` is used to render the message error.
// To override this, use the `error` type:
JsonEditor.setComponent('error', 'el-alert', ({ vm }) => ({
  type: 'error',
  title: vm.error,
}));
export default {
  data() {
    return {
      schema: this.schemas,
      model: this.models
    }
  },
  props: {
    schemas: {
      default: {},
      type: Object
    },
    models: {
      default: {},
      type: Object
    }
  },
  mounted() {
    
  },
  components: { JsonEditor },
  computed: {
    jsonString() {
      return JSON.stringify(this.model, null, 2).trim();
    },
  },
  methods: {
    submit(_e) {
      this.$refs.JsonEditor.form().validate(valid => {
        if (valid) {
          // 验证通过 提交信息
          console.log('model', JSON.stringify(this.model));
          this.$refs.JsonEditor.clearErrorMessage();
        } else {
          this.$refs.JsonEditor.setErrorMessage('请填写所需的信息!');
          return false;
        }
      });
    },
    reset() {
      this.$refs.JsonEditor.reset();
    },
  }
};
</script>

<style>
.form {
  text-align: left;
  width: 90%;
  margin: auto;
}
h2 {
  font-size: 1.7em;
  text-align: center;
  margin-top: 0;
  margin-bottom: 0.2em;
}
h2 + small {
  display: block;
  text-align: center;
  margin-bottom: 1.2em;
}
small {
  line-height: 20px;
  display: block;
}
.el-alert {
  margin-bottom: 15px;
}
.el-form .sub {
  margin-left: 0%;
}
.json {
  text-align: left;
}
</style>